{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Assembly Language\n", "\n", "Figure 7.2: The assembly language program to count occurrences of a character." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Assembled! Use %dis or %dump to examine; use %exe to run.\n" ] } ], "source": [ ";\n", "; Program to count occurrences of a character in a File.\n", "; Character to be input from the keyboard.\n", "; Result to be displayed on the monitor.\n", "; Program works only if no more than 9 occurrences are found.\n", ";\n", ";\n", "; Initialization\n", ";\n", " .ORIG x3000\n", " AND R2,R2,#0 ; R2 is counter, initialize to 0\n", " LD R3,PTR ; R3 is pointer to characters\n", " TRAP x23 ; R0 gets character input\n", " LDR R1,R3,#0 ; R1 gets the next character\n", ";\n", "; Test character for end of file\n", ";\n", "TEST ADD R4,R1,#-4 ; Test for EOT\n", " BRz OUTPUT ; If done, prepare the output\n", ";\n", "; Test character for match. If a match, increment count.\n", ";\n", " NOT R1,R1\n", " ADD R1,R1,R0 ; If match, R1 = xFFFF\n", " NOT R1,R1 ; If match, R1 = x0000\t\n", " BRnp GETCHAR ; If no match, do not increment\n", " ADD R2,R2,#1\n", ";\n", "; Get next character from the file\n", ";\n", "GETCHAR ADD R3,R3,#1 ; Increment the pointer\n", " LDR R1,R3,#0 ; R1 gets the next character to test\n", " BRnzp TEST \n", ";\n", "; Output the count.\n", ";\n", "OUTPUT LD R0,ASCII ; Load the ASCII template\n", " ADD R0,R0,R2 ; Convert binary to ASCII\n", " OUT ; ASCII code in R0 is displayed\n", " \n", " ;; Show a linefeed number to advance line:\n", " AND R0,R0, #0\n", " ADD R0,R0, #10\n", " TRAP x21 ; ASCII code in R0 is displayed\n", " TRAP x25 ; Halt machine\n", ";\n", "; Storage for pointer and ASCII template\n", ";\n", "ASCII .FILL x0030\n", "PTR: .FILL FILE\n", "FILE .STRINGZ \"xxxxxxxxxxxxxxxxxxxxxxxxxxyz\"\n", " .FILL #4\n", " .END" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "============================================================\n", "Memory disassembled:\n", "============================================================\n", " x3000: x54A0 AND R2, R2, #0 [line: 1]\n", " x3001: x2614 LD R3, PTR [line: 2]\n", " x3002: xF023 IN [line: 3]\n", " x3003: x62C0 LDR R1, R3, 0 [line: 4]\n", "TEST: x3004: x187C ADD R4, R1, #-4 [line: 8]\n", " x3005: x0408 BRz OUTPUT (or 8) [line: 9]\n", " x3006: x927F NOT R1, R1 [line: 13]\n", " x3007: x1240 ADD R1, R1, R0 [line: 14]\n", " x3008: x927F NOT R1, R1 [line: 15]\n", " x3009: x0A01 BRnp GETCHAR (or 1) [line: 16]\n", " x300A: x14A1 ADD R2, R2, #1 [line: 17]\n", "GETCHAR: x300B: x16E1 ADD R3, R3, #1 [line: 21]\n", " x300C: x62C0 LDR R1, R3, 0 [line: 22]\n", " x300D: x0FF6 BRnzp TEST [line: 23]\n", "OUTPUT: x300E: x2006 LD R0, ASCII [line: 27]\n", " x300F: x1002 ADD R0, R0, R2 [line: 28]\n", " x3010: xF021 OUT [line: 29]\n", " x3011: x5020 AND R0, R0, #0 [line: 32]\n", " x3012: x102A ADD R0, R0, #10 [line: 33]\n", " x3013: xF021 OUT [line: 34]\n", " x3014: xF025 HALT [line: 35]\n", "ASCII: x3015: x0030 NOOP - (no BR to x3046) (or 48, '0') [line: 39]\n", "PTR: x3016: x3017 ST R0, x302E [line: 40]\n", "FILE: x3017: x0078 NOOP - (no BR to x3090) (or 120, 'x') [line: 41]\n", " x3018: x0078 - 120 (or 120, 'x')\n", " x3019: x0078 - 120 (or 120, 'x')\n", " x301A: x0078 - 120 (or 120, 'x')\n", " x301B: x0078 - 120 (or 120, 'x')\n", " x301C: x0078 - 120 (or 120, 'x')\n", " x301D: x0078 - 120 (or 120, 'x')\n", " x301E: x0078 - 120 (or 120, 'x')\n", " x301F: x0078 - 120 (or 120, 'x')\n", " x3020: x0078 - 120 (or 120, 'x')\n", " x3021: x0078 - 120 (or 120, 'x')\n", " x3022: x0078 - 120 (or 120, 'x')\n", " x3023: x0078 - 120 (or 120, 'x')\n", " x3024: x0078 - 120 (or 120, 'x')\n", " x3025: x0078 - 120 (or 120, 'x')\n", " x3026: x0078 - 120 (or 120, 'x')\n", " x3027: x0078 - 120 (or 120, 'x')\n", " x3028: x0078 - 120 (or 120, 'x')\n", " x3029: x0078 - 120 (or 120, 'x')\n", " x302A: x0078 - 120 (or 120, 'x')\n", " x302B: x0078 - 120 (or 120, 'x')\n", " x302C: x0078 - 120 (or 120, 'x')\n", " x302D: x0078 - 120 (or 120, 'x')\n", " x302E: x0078 - 120 (or 120, 'x')\n", " x302F: x0078 - 120 (or 120, 'x')\n", " x3030: x0078 - 120 (or 120, 'x')\n", " x3031: x0079 - 121 (or 121, 'y')\n", " x3032: x007A - 122 (or 122, 'z')\n", " x3033: x0000 - \\0\n", " x3034: x0004 NOOP - (no BR to x3039) (or 4) [line: 42]\n" ] } ], "source": [ "%dis" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Input a character> A\n", "A\n", "0\n", "============================================================\n", "Computation completed\n", "============================================================\n", "Instructions: 544\n", "Cycles: 4012 (0.002006 milliseconds)\n", "\n", "============================================================\n", "Registers:\n", "============================================================\n", "PC: x048E\n", "N: 0 Z: 0 P: 1 \n", "R0: x000A R1: x0004 R2: x0000 R3: x3034 \n", "R4: x0000 R5: x0000 R6: x0000 R7: x3015 \n" ] } ], "source": [ "%exe" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First pass: Symbol Table\n", "\n", "Symbol | Address\n", "-------| -------\n", "TEST | x3004\n", "GETCHAR| x300B\n", "OUTPUT | x300E\n", "ASCII | x3015\n", "PTR | x3016\n", "FILE | x3017" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Second pass: computing offsets\n", "\n", "Consider:\n", "\n", "```\n", " LD R3,PTR ; R3 is pointer to characters\n", "```\n", "\n", "PTR is x3016. We know that PC+ (x3002) plus offset should equal x3016, so we simply subtract: x3016 - x3002 to get x0014. Is this what the %dis shows?\n", "\n", "```\n", "x3001: x2614 - 0010 0110 0001 0100 - 0010 011 0 0001 0100\n", " LD R3 x14\n", " LD R3 #20\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## High-Level Programming Concepts\n", "\n", "### Declaration of Variables\n", "\n", "High-level | LC3\n", ":-----------| :----\n", "int a; // simple variable (uninitialized)| a .BLKW 1 ; simple variable (or .FILL 0)\n", "int b = 2014; // simple initialized variable | b .FILL #2014 ; simple initialized variable\n", "int c[10]; // array of 10 (uninitialized) | c .BLKW 10 ; array of ten ints (initialized to 0)\n", "int *d = &e; // address of e | d .FILL e ; store address of e in variable d\n", "\n", "### Assignment of values\n", "\n", "\n", "High-level | LC3\n", ":-----------| :----\n", "b = a; | LD R0, a ; load from memory to a register\n", " | ST R0, b ; store from register to memory\n", "b = a + 1; | LD R0, a ; load from memory to a register\n", " | ADD R0, R0, #1 ; increment value\n", " | ST R0, b ; store from register to memory\n", "\n", "\n", "### Assignment using pointers\n", "\n", "High-level | LC3\n", ":-----------| :----\n", "pa = &a; | LEA R0, a ; get the address of the variable\n", " | ST R0, pa ; store it in the pointer variable\n", "b = *pa; | LDI R0, pa ; get the value at the address stored in pa\n", " | ST R0, b ; store it in b\n", "*pa = b; | LD R0, b ; load the value of b\n", " | STI R0, pa ; store it at the address stored in pa\n", "\n", "### Comparison: if\n", "\n", "\n", "High-level | LC3\n", ":-----------| :----\n", "if (a < b) { | LD R0, a ; load a\n", " | LD R1, b ; load b\n", " | NOT R1, R1 ; begin 2's complement of b\n", " | ADD R1, R1, #1 ; R1 now has -b\n", " | ADD R0, R0, R1 ; R0 = a + (-b)\n", " | ; condition code now set\n", " | BRzp SKIP ; if false, skip over code\n", "// do something | ; code to do something (the then clause)\n", "} | SKIP ; remainder of code after if\n", "\n", "\n", "### Comparison: if/else\n", "\n", "**High-level**\n", "\n", "```c\n", "uint a = 1;\n", "uint b = 2;\n", "\n", "if (a < b) {\n", " // do something\n", "}\n", "else {\n", " // do something else\n", "}\n", "```\n", "\n", "**LC-3**\n", "\n", "```gas\n", " LD R0, A ; load a\n", " LD R1, B ; load b\n", " NOT R1, R1 ; begin 2's complement of b\n", " ADD R1, R1, #1 ; R1 now has -b\n", " ADD R0, R0, R1 ; R0 = a + (-b)\n", " ; condition code now set\n", " BRzp ELSE ; if false, skip over code\n", " ; do something \n", " BR END_ELSE ; don't execute else code\n", "ELSE: ; code for else clause here\n", " ; do something else\n", "END_ELSE: ; remainder of code after else\n", " HALT\n", "A: .FILL x01\n", "B: .FILL x02\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Designing Large Programs" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Assembled! Use %dis or %dump to examine; use %exe to run.\n" ] } ], "source": [ " .ORIG x4000\n", " \n", " ;;JSR START\n", " ;;HALT\n", " \n", " LEA R0, START\n", " JSRR R0\n", " HALT \n", " \n", "START ST R7,SaveR7\n", " JSR SaveReg\n", " ;; \n", " ;; do lots of stuff that messes with all of the resgisters!!\n", " ;; \n", " JSR RestoreReg\n", " LD R7,SaveR7\n", " RET ; JMP R7 terminates \n", "\n", "SaveR7 .FILL x0000 ;; close to where it is used\n", "\n", "SaveReg ST R1,SaveR1\n", " ST R2,SaveR2\n", " ST R3,SaveR3\n", " ST R4,SaveR4\n", " ST R5,SaveR5\n", " ST R6,SaveR6\n", " RET\n", ";\n", "RestoreReg LD R1,SaveR1\n", " LD R2,SaveR2\n", " LD R3,SaveR3\n", " LD R4,SaveR4\n", " LD R5,SaveR5\n", " LD R6,SaveR6\n", " RET\n", "SaveR1 .FILL x0000\n", "SaveR2 .FILL x0000\n", "SaveR3 .FILL x0000\n", "SaveR4 .FILL x0000\n", "SaveR5 .FILL x0000\n", "SaveR6 .FILL x0000\n", " .END" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "============================================================\n", "Computation completed\n", "============================================================\n", "Instructions: 22\n", "Cycles: 187 (0.000093 milliseconds)\n", "\n", "============================================================\n", "Registers:\n", "============================================================\n", "PC: x048E\n", "N: 0 Z: 0 P: 1 \n", "R0: x4003 R1: x0000 R2: x0000 R3: x0000 \n", "R4: x0000 R5: x0000 R6: x0000 R7: x4003 \n" ] } ], "source": [ "%exe" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Calysto LC3", "language": "asm", "name": "calysto_lc3" }, "language_info": { "file_extension": ".asm", "mimetype": "text/x-gas", "name": "gas" } }, "nbformat": 4, "nbformat_minor": 2 }